package com.jie.component.lock.core;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.jie.common.util.LogUtil;
import com.jie.component.init.base.AbstractApplicationPostConstructHandler;
import com.jie.component.lock.locker.*;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

import static com.jie.component.lock.core.LockType.*;

/**
 * @author jie
 * @version 1.0 2025-02-09
 */
public class ManageLocker extends AbstractApplicationPostConstructHandler {

    private final Map<LockType, ServiceLocker> cacheLocker = new HashMap<>();

    private Cache<String, ReentrantLock> localCacheLocker;

    /**
     * 本地锁的过期时间
     */
    @Value("${lock.local.durationTime:48}")
    private Integer durationTime;

    public ManageLocker(RedissonClient redissonClient) {
        cacheLocker.put(Reentrant, new RedissonReentrantLocker(redissonClient));
        cacheLocker.put(Fair, new RedissonFairLocker(redissonClient));
        cacheLocker.put(Write, new RedissonWriteLocker(redissonClient));
        cacheLocker.put(Read, new RedissonReadLocker(redissonClient));
    }

    public ServiceLocker getReentrantLocker() {
        return cacheLocker.get(Reentrant);
    }

    public ServiceLocker getFairLocker() {
        return cacheLocker.get(Fair);
    }

    public ServiceLocker getWriteLocker() {
        return cacheLocker.get(Write);
    }

    public ServiceLocker getReadLocker() {
        return cacheLocker.get(Read);
    }

    /**
     * 获取本地锁，没有则添加一个本地锁
     * @param lockKey
     * @param fair
     * @return
     */
    public ReentrantLock getLocalLock(String lockKey, boolean fair) {
        return localCacheLocker.get(lockKey, key -> new ReentrantLock(fair));
    }

    @Override
    public Integer executeOrder() {
        return 0;
    }

    /**
     * caffeine是线程安全的
     * @param context 容器上下文
     */
    @Override
    public void executeInit(ConfigurableApplicationContext context) {
        LogUtil.initLog("本地锁的caffeine缓存");
        localCacheLocker = Caffeine.newBuilder()
                .expireAfterWrite(durationTime, TimeUnit.HOURS)
                .build();
    }
}
